/**
 * www.easyplatform.cn ©2016
 */
package cn.easyplatform.studio.web.editors.workbench;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.studio.StudioApp;
import cn.easyplatform.studio.cmd.identity.GetStudioRolesCmd;
import cn.easyplatform.studio.cmd.identity.GetStudioUsersCmd;
import cn.easyplatform.studio.cmd.identity.StudioUserPasswordResetCmd;
import cn.easyplatform.studio.cmd.identity.UpdateStudioUserCmd;
import cn.easyplatform.studio.context.Contexts;
import cn.easyplatform.studio.utils.SecurityUtils;
import cn.easyplatform.studio.utils.StringUtil;
import cn.easyplatform.studio.utils.WebUtils;
import cn.easyplatform.studio.vos.LoginUserVo;
import cn.easyplatform.studio.vos.RoleVo;
import cn.easyplatform.studio.vos.UserVo;
import cn.easyplatform.studio.web.editors.AbstractPanelEditor;
import cn.easyplatform.studio.web.layout.WorkbenchController;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zkmax.zul.Cascader;
import org.zkoss.zkmax.zul.Chosenbox;
import org.zkoss.zul.*;
import org.zkoss.zul.theme.Themes;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author <a href="mailto:shiny_vc@163.com">陈云亮</a> <br/>
 * @since 2.0.0 <br/>
 */
public class UserEditor extends AbstractPanelEditor {

    private Listbox userGrid;

    private Textbox key;

    private Textbox name;

    private Textbox password;

    private Datebox validDate;

    private Intbox validDays;

    private Combobox theme;

    private Combobox editorTheme;

    private Chosenbox roleId;

    private Combobox state;

    private UserVo selectedUser;

    private List<RoleVo> roles;

    public UserEditor(WorkbenchController workbench, String id) {
        super(workbench, id);
    }

    @Override
    public void create(Object... args) {
        Idspace is = createPanel(Labels.getLabel("menu.studio.user"), "~./images/user.png", "~./include/editor/workbench/user.zul");
        for (Component comp : is.getFellows()) {
            if (comp.getId().equals("workbenchUser_listbox_userGrid")) {
                userGrid = (Listbox) comp;
                userGrid.getPaginal().setDetailed(false);
            } else if (comp.getId().equals("workbenchUser_textbox_id"))
                key = (Textbox) comp;
            else if (comp.getId().equals("workbenchUser_textbox_name"))
                name = (Textbox) comp;
            else if (comp.getId().equals("workbenchUser_textbox_password"))
                password = (Textbox) comp;
            else if (comp.getId().equals("workbenchUser_datebox_validDate")) {
                validDate = (Datebox) comp;
            } else if (comp.getId().equals("workbenchUser_intbox_validDays")) {
                validDays = (Intbox) comp;
            } else if (comp.getId().equals("workbenchUser_combobox_theme")) {
                theme = (Combobox) comp;
                String[] themes = Themes.getThemes();
                for (int i = 0; i < themes.length; i++) {
                    if (themes[i].equals("zen") || themes[i].equals("iceblue"))
                        continue;
                    Comboitem ci = new Comboitem(Themes.getDisplayName(themes[i]));
                    ci.setValue(themes[i]);
                    theme.appendChild(ci);
                }
            } else if (comp.getId().equals("workbenchUser_chosenbox_roleId")) {
                roleId = (Chosenbox) comp;

            } else if (comp.getId().equals("workbenchUser_combobox_editorTheme")) {
                editorTheme = (Combobox) comp;
            } else if (comp.getId().equals("workbenchUser_combobox_state")) {
                state = (Combobox) comp;
                state.setSelectedIndex(0);
            } else if (comp instanceof Button) {
                String AuthorizedKey = null;
                if (comp.getId().equals("workbenchUser_button_studioUserAdd"))
                    AuthorizedKey = "menuAdd";
                else if (comp.getId().equals("workbenchUser_button_studioUserDelete"))
                    AuthorizedKey = "menuDelete";
                else if (comp.getId().equals("workbenchUser_button_studioUserEdit"))
                    AuthorizedKey = "menuEdit";
                else if (comp.getId().equals("workbenchUser_button_studioUserReset"))
                    AuthorizedKey = "menuEdit";
                boolean isAuthorized = Contexts.getUser().isAuthorized(AuthorizedKey);
                if (isAuthorized)
                    comp.addEventListener(Events.ON_CLICK, this);
                else
                    ((Button) comp).setDisabled(true);
            }/* else if (comp.getId().equals("workbenchUser_cascader_default")) {
                defultProduct = (Cascader) comp;
            }*/
        }
        redraw();
        selectedUser = new UserVo();
        selectedUser.setCode('C');
        setValue();
    }

    private void redraw() {
        List<UserVo> users = StudioApp.execute(new GetStudioUsersCmd());
        for (UserVo user : users) {
            Listitem row = new Listitem();
            row.setValue(user);
            row.appendChild(new Listcell(user.getId()));
            row.appendChild(new Listcell(user.getName()));
            row.addEventListener(Events.ON_CLICK, this);
            userGrid.appendChild(row);
        }
        roles = StudioApp.execute(new GetStudioRolesCmd());
        RoleVo roleVo = new RoleVo();
        roleVo.setId(LoginUserVo.UserType.ADMIN.getName());
        roles.add(roleVo);
        ListModelList<String> model = new ListModelList<>(roles.size());
        for (RoleVo field : roles) {
            model.add(field.getId());
        }
        roleId.setModel(model);
    }

    private void setValue() {
        key.setValue(selectedUser.getId());
        name.setValue(selectedUser.getName());
        password.setValue(selectedUser.getPassword());
        validDate.setValue(selectedUser.getValidDate());
        validDays.setValue(selectedUser.getValidDays());
        if (Strings.isBlank(selectedUser.getTheme()))
            theme.setSelectedIndex(0);
        else {
            for (Comboitem ci : theme.getItems()) {
                if (ci.getValue().equals(selectedUser.getTheme())) {
                    theme.setSelectedItem(ci);
                    break;
                }
            }
        }
        if (Strings.isBlank(selectedUser.getEditorTheme()))
            editorTheme.setSelectedIndex(0);
        else {
            for (Comboitem ci : editorTheme.getItems()) {
                if (ci.getValue().equals(selectedUser.getEditorTheme())) {
                    editorTheme.setSelectedItem(ci);
                    break;
                }
            }
        }
        List<String> allRole = new ArrayList<>();
        List<String> roleList = new ArrayList<>();
        List<String> containRole = new ArrayList<>();
        if (Strings.isBlank(selectedUser.getRoleId()) == false) {
            roleList = Arrays.asList(selectedUser.getRoleId().split(","));
        }
        for (RoleVo field : roles) {
            allRole.add(field.getId());
        }
        if (roleList.size() > 0) {
            for (String roleId : roleList) {
                if (allRole.contains(roleId)) {
                    containRole.add(roleId);
                }
            }
        }
        roleId.setSelectedObjects(containRole);
        state.setSelectedIndex(selectedUser.getState());

        /*List<ProjectRoleVo> projectRoleVoList = Contexts.getUser().getRoleVoList();
        List<DefaultTreeNode> firstNodeList = new ArrayList<>();
        for (ProjectRoleVo roleVo : projectRoleVoList) {
            List<DefaultTreeNode> secondNodeList = new ArrayList<>();
            if (Strings.isBlank(roleVo.getRoleIDs()) == false) {
                String[] roles = roleVo.getRoleIDs().split(",");
                for (String roleId : roles) {
                    secondNodeList.add(new DefaultTreeNode(roleId));
                }
            }
            DefaultTreeNode firstNode = new DefaultTreeNode(roleVo.getProjectId(), secondNodeList);
            firstNodeList.add(firstNode);
        }
        DefaultTreeNode treeNode = new DefaultTreeNode("ROOT", firstNodeList);
        DefaultTreeModel defaultTreeModel = new DefaultTreeModel(treeNode);
        defultProduct.setModel(defaultTreeModel);*/
    }

    @Override
    public void dispatch(Event event) {
        if (event.getTarget() instanceof Button) {
            if (event.getTarget().getId().equals("workbenchUser_button_studioUserReset")) {
                if (selectedUser == null || selectedUser.getCode() == 'C') {
                    WebUtils.showError(Labels.getLabel("editor.select",
                            new String[]{Labels.getLabel("menu.studio.user")}));
                    return;
                }
                WebUtils.showConfirm(Labels.getLabel("editor.user.password.reset"), new EventListener<Event>() {
                    public void onEvent(Event event) throws Exception {
                        if (event.getName().equals(Events.ON_OK)) {
                            String password = StudioApp.execute(event.getTarget(),
                                    new StudioUserPasswordResetCmd(selectedUser.getId(), selectedUser.getSalt()));
                            WebUtils.showInfo(Labels.getLabel(
                                    "editor.user.password.reset.title", new String[]{
                                            selectedUser.getId(), password}));
                        }
                    }
                });
            } else if (event.getTarget().getId().equals("workbenchUser_button_studioUserAdd")) {
                selectedUser = new UserVo();
                selectedUser.setCode('C');
                key.setReadonly(false);
                password.setReadonly(false);
                roleId.setSelectedObjects(null);
                setValue();
            } else if (event.getTarget().getId().equals("workbenchUser_button_studioUserDelete")) {
                if (selectedUser == null || selectedUser.getCode() == 'C') {
                    WebUtils.showError(Labels.getLabel("editor.select",
                            new String[]{Labels.getLabel("menu.studio.user")}));
                    return;
                }
                WebUtils.showConfirm(Labels.getLabel("button.delete"), this);
            } else if (event.getTarget().getId().equals("workbenchUser_button_studioUserEdit")) {//save
                if (selectedUser == null) {
                    WebUtils.showError(Labels.getLabel("editor.select",
                            new String[]{Labels.getLabel("menu.studio.user")}));
                    return;
                }
                if (Strings.isBlank(key.getValue())) {
                    WebUtils.notEmpty("ID");
                    return;
                }
                if (Strings.isBlank(name.getValue())) {
                    WebUtils.notEmpty(Labels.getLabel("entity.name"));
                    return;
                }
                if (Strings.isBlank(password.getValue())) {
                    WebUtils.notEmpty(Labels.getLabel("user.password"));
                    return;
                }
                if (roleId.getSelectedObjects()==null) {
                    WebUtils.notEmpty(Labels.getLabel("editor.user.role"));
                    return;
                }
                selectedUser.setId(key.getValue());
                if (selectedUser.getCode() == 'C') {
                    selectedUser.setSalt(SecurityUtils.getSalt());
                    selectedUser.setPassword(SecurityUtils.getSecurePassword(password.getValue(), selectedUser.getSalt()));
                    password.setValue(selectedUser.getPassword());
                }
                selectedUser.setName(name.getValue());
                selectedUser.setValidDate(validDate.getValue());
                selectedUser.setValidDays(validDays.getValue());
                selectedUser.setTheme(theme.getSelectedItem().getValue().toString());
                selectedUser.setEditorTheme(editorTheme.getSelectedItem().getValue().toString());
                List<String> roleList = new ArrayList<>();
                for (Object obj:roleId.getSelectedObjects()){
                    roleList.add(obj+"");
                }
                selectedUser.setRoleId(StringUtil.listToString(roleList, ","));
                selectedUser.setState(state.getSelectedIndex());
                if (StudioApp.execute(event.getTarget(), new UpdateStudioUserCmd(
                        selectedUser))) {
                    if (selectedUser.getCode() == 'C') {
                        Listitem row = new Listitem();
                        row.setValue(selectedUser);
                        row.appendChild(new Listcell(selectedUser.getId()));
                        row.appendChild(new Listcell(selectedUser.getName()));
                        row.addEventListener(Events.ON_CLICK, this);
                        row.setSelected(true);
                        userGrid.appendChild(row);
                    } else {
                        Listitem row = getSelectedRow();
                        List<Listcell> labels = row.getChildren();
                        labels.get(0).setLabel(selectedUser.getId());
                        labels.get(1).setLabel(selectedUser.getName());
                    }
                    selectedUser.setCode('U');
                    password.setReadonly(true);
                    WebUtils.showSuccess(Labels.getLabel("button.save")
                            + Labels.getLabel("menu.studio.user")
                            + selectedUser.getId());
                }
            }
        } else if (event.getName().equals(Events.ON_OK)) {
            selectedUser.setCode('D');
            if (StudioApp.execute(new UpdateStudioUserCmd(selectedUser))) {
                getSelectedRow().detach();
                selectedUser = new UserVo();
                selectedUser.setCode('C');
                key.setReadonly(false);
                password.setReadonly(false);
                setValue();
            }
        } else if (event.getTarget() instanceof Listitem) {
            Listitem row = (Listitem) event.getTarget();
            selectedUser = row.getValue();
            selectedUser.setCode('U');
            key.setReadonly(true);
            password.setReadonly(true);
            setValue();
        }
    }

    private Listitem getSelectedRow() {
        if (selectedUser == null || selectedUser.getCode() == 'C')
            return null;
        return userGrid.getSelectedItem();
    }
}
